<template>
  <div class="form-wrappers">
    <el-form :model="resource" :rules="rules" ref="form" class="form-wrapper">
      <el-row class="syfm">
        <el-form-item prop="url" label="实验资源">
          <div
            class="drop-area el-upload-dragger"
            @click="clickElement($event, 'upload_folder')"
            @drop="handleFileDrop($event)"
            @dragleave="stopEvent($event)"
            @dragenter="stopEvent($event)"
            @dragover="stopEvent($event)"
          >
            <!-- <i class="el-icon-upload"></i> -->

            <img src="@/images/syzyicon.png" alt="" class="teximg" />

            <div class="el-upload__text">
              请将资源文件目录拖拽到此处,或点此添加
              <br />
              <!-- TODO 在方法中判断 -->
              <div class="scjd">
                <em v-if="allFileNum > 0 && allFileNum === upFileNum"
                  >已上传</em
                >
                <em v-if="allFileNum > 0 && allFileNum > upFileNum"
                  >正在上传：{{ upFileNum }}/{{ allFileNum }}</em
                >
              </div>
              <!-- <em v-if="!isModify && allFileNum == 0" style="color: #F56C6C;"
                >未上传, 请选择目录</em
              > -->
              <div
                class="zyscts"
                v-if="!allFileNum && isModify"
                v-html="resourceMessage"
              ></div>
              <input
                ref="upload_folder"
                webkitdirectory
                type="file"
                style="display: none"
                @change="handleFileInput($event)"
              />
            </div>
          </div>
        </el-form-item>
      </el-row>

      <!-- <el-row>
        <el-col :span="10">
          <el-form-item prop="vrType" label="实验类别">
            <el-select v-model="resource.vrType" placeholder="请选择实验类别">
              <el-option
                v-for="item in vrTypes"
                :key="item.id"
                :label="item.title"
                :value="item.id"
              ></el-option>
            </el-select>
          </el-form-item>

          <el-row>
            <el-col :span="12">
              <el-form-item prop="majorId" label="所属专业">
                <el-select
                  v-model="resource.majorId"
                  placeholder="请选择所属专业"
                  :disabled="isLock"
                  @change="resetType"
                >
                  <el-option
                    v-for="item in majors"
                    :key="item.id"
                    :label="item.title"
                    :value="item.id"
                  ></el-option>
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item prop="typeId" label="所属类别">
                <el-select
                  v-model="resource.typeId"
                  placeholder="请选择所属类别"
                  :disabled="isLock"
                >
                  <el-option
                    v-for="item in types"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                  ></el-option>
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>
          <el-row>
            <el-col :span="12">
              <el-form-item prop="mode" label="实验模式">
                <el-select
                  v-model="resource.mode"
                  placeholder="请选择实验模式"
                  :disabled="isLock"
                >
                  <el-option
                    v-for="item in modes"
                    :key="item.value"
                    :label="item.name"
                    :value="item.value"
                  ></el-option>
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item prop="state" label="实验状态">
                <el-switch
                  v-model="resource.state"
                  active-text="启用"
                  inactive-text="禁用"
                  :active-value="1"
                  :inactive-value="0"
                ></el-switch>
              </el-form-item>
            </el-col>
          </el-row>
          <el-row v-if="isModify">
            <el-col :span="12">
              <el-form-item label="创建时间">
                <el-input v-model="resource.createTime" readonly />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="上次更新">
                <el-input v-model="resource.updateTime" readonly />
              </el-form-item>
            </el-col>
          </el-row>
        </el-col>
      </el-row> -->
      <el-row>
        <el-form-item prop="context" label="更新内容" class="gnrbox">
          <!-- <el-input
            v-model="resource.context"
            type="textarea"
            :rows="3"
            class="gxnr"
          /> -->
          <vue-editor
            id="editor"
            v-model="resource.context"
            :editorToolbar="editorToolbar"
            class="gxnr"
          />
        </el-form-item>
      </el-row>
    </el-form>
  </div>
</template>

<script>
import { VueEditor } from 'vue2-editor'
import { createMultipartUpload, listObjects } from '@/utils/oss.js'
import {
  listResourceMode,
  listMajorByPid,
  checkCode
} from '@/api/simulation.js'
import { majorList } from '@/api/major.js'
import { deptList } from '@/api/sysDept.js'
export default {
  components: {
    VueEditor
  },
  props: {
    resource: {
      type: Object,
      default: () => ({})
    },
    isModify: {
      type: Boolean,
      default: true
    }
  },
  data() {
    const that = this

    return {
      modes: [], // 实验模式参数列表
      majors: [], // 专业参数列表
      types: [], // 类别参数列表
      isLock: false, // `isLock: true` 后可以上传文件, 禁止上传后修改路径
      objects: [],
      videoFlag: false,
      videoProgress: 0,
      coverFlag: false,
      coverProgress: 0,
      allFileNum: 0,
      upFileNum: 0,
      resourceMessage: '', // 资源上传框提示信息
      depts: [],
      vrTypes: [
        {
          id: '国家申报',
          title: '国家申报'
        },
        {
          id: '定制化',
          title: '定制化'
        }
      ],
      // 表单校验
      rules: {
        version: [
          {
            required: true,
            message: '请输入版本号',
            trigger: 'blur'
          }
        ],

        url: [
          {
            required: true,
            message: '请上传实验资源',
            trigger: 'blue'
          }
        ]
      },
      // 富文本参数
      editorToolbar: [
        [
          {
            header: [false, 1, 2, 3, 4, 5, 6]
          },
          'bold',
          'italic',
          'underline',
          {
            align: ''
          },
          {
            align: 'center'
          },
          {
            align: 'right'
          }
        ],
        [
          {
            list: 'ordered'
          },
          {
            list: 'bullet'
          },
          {
            list: 'check'
          }
        ],
        [
          {
            background: []
          },
          {
            color: []
          }
        ],
        ['strike'],
        ['clean']
      ]
    }
  },
  created() {
    this.getDeptList()
    this.initForm()
    this.listResourceMode()
  },
  methods: {
    getDeptList() {
      deptList({}).then(async res => {
        this.depts = res.children
      })
    },
    // ==================== 文件上传 ====================
    /**
     * 图片 / 视频上传
     */
    handleFileUpload(option, attribute) {
      const { file } = option
      const suffix = file.name.slice(file.name.lastIndexOf('.'))
      const { majorId, typeId, code, version } = this.resource
      const key = `vrOrg/${majorId}/${typeId}/${code}/${version}/${attribute}/${this.createUUID()}${suffix}`
      createMultipartUpload(key, file, (progress, checkpoint) => {
        if (!checkpoint) {
          return
        }
        this[`${attribute}Flag`] = true
        this[`${attribute}Progress`] = Math.round(progress * 100)
      }).then(res => {
        const url = res.res.requestUrls[0]
        this.$set(
          this.resource,
          attribute,
          url.indexOf('?') === -1 ? url : url.slice(0, url.indexOf('?'))
        )
        this.videoFlag = false
        this.videoProgress = 0
        this.coverFlag = false
        this.coverProgress = 0
      })
    },
    checkSuccess() {
      this.allFileNum = this.objects.length
      this.upFileNum = this.objects.filter(
        item => item.uploading === false
      ).length
      if (this.allFileNum == this.upFileNum) {
        this.$refs['upload_folder'].value = ''
      }
    },
    /**
     * 资源文件上传
     * @param {File} file 本地文件
     * @param {String} relativePath 文件相对路径
     */
    handleResourceUpload(file, relativePath) {
      const that = this
      const { majorId, typeId, code, version } = this.resource
      const key = `vrOrg/${majorId}/${typeId}/${code}/${version}/${relativePath}`
      // 检查重复上传
      let index = this.objects.findIndex(item => item.key === key)
      if (index > -1) {
        this.objects[index].file = file
        return
      }
      // 上传
      this.objects.push({
        key: key,
        file: file,
        uploading: true
      })
      createMultipartUpload(key, file, this.multiUploadProgress).then(
        ({ name, res }) => {
          const target = that.objects.find(object => object.key === key)
          target.uploading = false
          // 更新lock状态
          that.checkSuccess()
          if (that.upFileNum === that.allFileNum) {
            that.$set(that, 'isLock', false)
          }
          // 通过任一 url 截取资源文件父目录, 通过 json 文件地址截取资源名称
          // url: http://zf-vr.oss-cn-hangzhou.aliyuncs.com/6/8/jyjb1/1.0.0/Build/MRWebGl.json
          const durl = /https?:\/\/[\w.:\-_%]*\/[\w.\-_%]*\/[\w.\-_%]*\/[\w.\-_%]*\/[\w.\-_%]*\/[\w.\-_%]*\/[\w.\-_%]*\//i
          const jurl = /[\w.:\-_\/%]*\/Build\/[\w.\-_%]*.json/i
          this.resource.url = res.requestUrls[0].match(durl)[0]
          if (name && name.match(jurl)) {
            const node = res.requestUrls[0].split('/')
            this.resource.attachPrefix = node[node.length - 1].replace(
              '.json',
              ''
            )
          }
        }
      )
    },
    /**
     * 分片上传进度
     * @param {Number} progress 分片上传进度, 取值范围: 0~1
     * @param {Object} checkpoint 本地分片上传结果
     */
    multiUploadProgress(progress, checkpoint) {
      if (!checkpoint) {
        return
      }
      const target = this.objects.find(item => item.key === checkpoint.name)
      this.$set(target, 'checkpoint', checkpoint)
      this.$set(target, 'progress', Math.round(progress * 100))
    },
    /**
     * 点击上传文件 / 目录
     */
    handleFileInput(event) {
      const that = this
      this.checkField()
        .then(() => {
          // 校验通过, 上传, 禁止修改
          this.isLock = true
          for (const file of event.target.files) {
            that.handleResourceUpload(
              file,
              file.webkitRelativePath || file.name
            )
          }
        })
        .catch(() => {
          // 不通过, 清空上传
          this.$refs['upload_folder'].value = ''
        })
    },
    /**
     * 拖拽上传文件 / 目录
     */
    handleFileDrop(event) {
      this.stopEvent(event)
      this.checkField()
        .then(() => {
          this.isLock = true
          const items = event.dataTransfer.items
          if (!items.length || items[0].kind !== 'file') return
          for (const item of items) {
            const entry = item.webkitGetAsEntry()
            this.loadChildFiles(entry, entry.name)
          }
        })
        .catch(() => {
          this.$refs['upload_folder'].value = ''
        })
    },
    /**
     * 递归获取文件
     * @param {FileSystemEntry|FileSystemDirectoryEntry} entry 文件 / 目录
     * @param {String} relativePath 文件/目录相对路径
     */
    loadChildFiles(entry, relativePath) {
      const that = this
      if (entry.isFile) {
        entry.file(file => that.handleResourceUpload(file, relativePath))
        return
      }
      const reader = entry.createReader()
      reader.readEntries(entries =>
        entries.forEach(entry =>
          that.loadChildFiles(
            entry,
            `${relativePath ? relativePath : ''}/${entry.name}`
          )
        )
      )
    },
    // ==================== 页面动作 ====================
    /**
     * 初始化页面
     */
    initForm() {
      this.objects = []
      this.$set(this.resource, 'majorId', '1')
      this.$set(this.resource, 'typeId', '1')
      this.checkOSSResource()
    },
    async checkOSSResource() {
      // 验证 OSS 文件目录存在
      const { res } = await listObjects(this.resource.url)
      this.resourceMessage =
        res.requestUrls && res.requestUrls.length
          ? `<em style="color: #67C23A">服务器存在本实验资源</em>`
          : '<em style="color: #F56C6C">资源已被删除, 需重新上传</em>'
      console.log(this.resourceMessage)
    },
    /**
     * 数据处理, 表单验证
     */
    beforeSubmit() {
      if (!this.resource.attachPrefix) {
        this.$message('实验资源中无json文件')
        return false
      }
      if (this.allFileNum > this.upFileNum) {
        this.$message('文件上传中')
        return false
      }
      const { content } = this.resource.introductionJson
      const text = content.replace(/<[^>]+>/g, '')
      this.resource.introduction = JSON.stringify({
        content,
        text
      })
      return new Promise((resolve, reject) => {
        this.$refs['form'].validate(valid => {
          if (!valid) {
            return false
          }
          resolve()
        })
      })
    },
    /**
     * 上传参数全部通过
     */
    checkField() {
      const that = this
      const filed = ['code', 'version', 'mode']
      return new Promise((resolve, reject) => {
        let success = true
        that.$refs['form'].validateField(filed, error => {
          if (error) {
            success = false
          }
        })
        if (success) {
          resolve()
        } else {
          this.$refs['upload_folder'].value = ''
          this.$message.error('请检查上传必要参数')
        }
      })
    },
    resetForm() {
      this.$refs['form'].resetFields()
    },
    // ==================== 参数列表 ====================
    /**
     * 选择专业重置类型
     */
    resetType() {
      this.$set(this.resource, 'typeId', null)
      this.listType()
    },
    /**
     * 实验资源使用模式
     */
    listResourceMode() {
      listResourceMode().then(({ code, msg, data }) => {
        this.modes = data
      })
    },
    /**
     * 专业查询
     */
    listMajor() {
      majorList({}).then(res => {
        this.majors = res.children
      })
    },
    /**
     * 类型查询
     */
    listType() {
      listMajorByPid(this.resource.majorId).then(({ code, msg, data }) => {
        this.types = data
      })
    },
    // ==================== utils ====================
    /**
     * 图片格式验证
     */
    checkImageType({ type }) {
      const isPic = type.startsWith('image')
      if (!isPic) {
        this.$message.error('封面必须是 图片！')
      }
      return isPic
    },
    /**
     * 视频格式验证
     */
    checkVideoType({ type }) {
      const isVideo = type.startsWith('video')
      if (!isVideo) {
        this.$message.error('演示必须是 视频！')
      }
      return isVideo
    },
    /**
     * 阻止浏览器默认操作
     */
    stopEvent(event) {
      event.stopPropagation()
      event.preventDefault()
    },
    /**
     * 模拟点击
     */
    clickElement(event, el) {
      event.stopPropagation()
      this.$refs[el].click()
    },
    /**
     * 随机串
     */
    createUUID() {
      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
        let r = (Math.random() * 16) | 0,
          v = c == 'x' ? r : (r & 0x3) | 0x8
        return v.toString(16)
      })
    }
  }
}
</script>
<style scoped>
.el-form-item {
  display: flex !important;
}
.drop-area {
  width: 359px;
  height: 143px;
  /* line-height: 143px; */
}
.drop-areas {
  margin-left: 50px;
}
.drop-areass {
  margin-left: 75px;
}
.syfm {
  display: flex;
}
.el-form-item--medium .el-form-item__content {
  line-height: 0px !important;
}
.teximg {
  margin-top: 25px;
}
.symc {
  display: flex;
}
.zyscts {
  margin-top: -13px;
}
.gxnr {
  width: 359px;
  height: 150px;
}

.gnrbox {
  margin-left: 10px;
}
.scjd {
  margin-top: -10px;
}
</style>
